import socket
import struct
import time
from lxml import etree


class UniMRCPError(Exception):
    """UniMRCP相关异常"""
    pass


class UniMRCPConnection:
    """管理与UniMRCP服务器的连接"""

    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.sock = None
        self.connected = False

    def connect(self):
        """建立TCP连接"""
        try:
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.sock.connect((self.host, self.port))
            self.connected = True
            return True
        except Exception as e:
            raise UniMRCPError(f"连接失败: {str(e)}")

    def send(self, data):
        """发送数据到服务器"""
        if not self.connected:
            raise UniMRCPError("未建立连接")
        self.sock.sendall(data)

    def receive(self, buffer_size=4096):
        """从服务器接收数据"""
        if not self.connected:
            raise UniMRCPError("未建立连接")
        return self.sock.recv(buffer_size)

    def close(self):
        """关闭连接"""
        if self.connected:
            self.sock.close()
            self.connected = False


class MRCPMessageBuilder:
    """构建MRCP消息"""

    @staticmethod
    def build_tts_request(text, request_id=None):
        """构建文本转语音请求"""
        # 生成唯一请求ID
        request_id = request_id or int(time.time() * 1000)

        # 构建MRCPv2请求行
        request_line = f"SYNTHESIZE {request_id} MRCP/2.0\r\n"

        # 构建请求头
        headers = (
            f"Content-Type: application/synthesis+ssml\r\n"
            f"Content-Length: {len(text)}\r\n"
            f"Channel-Identifier: 1\r\n\r\n"
        )

        # 组合完整请求
        return f"{request_line}{headers}{text}".encode('utf-8')


class SSMLGenerator:
    """生成SSML（语音合成标记语言）内容"""

    @staticmethod
    def generate(text, voice="default", rate="medium"):
        """生成基本的SSML文档"""
        ssml = etree.Element("speak", version="1.0", xmlns="http://www.w3.org/2001/10/synthesis")
        voice_elem = etree.SubElement(ssml, "voice", name=voice)
        prosody = etree.SubElement(voice_elem, "prosody", rate=rate)
        prosody.text = text

        return etree.tostring(ssml, pretty_print=True, encoding='unicode')


class UniMRCPTTSService:
    """UniMRCP文本转语音服务"""

    def __init__(self, host, port):
        self.connection = UniMRCPConnection(host, port)
        self.builder = MRCPMessageBuilder()
        self.ssml_generator = SSMLGenerator()

    def synthesize(self, text, voice="default", rate="medium"):
        """合成语音"""
        try:
            # 连接服务器
            self.connection.connect()

            # 生成SSML内容
            ssml_content = self.ssml_generator.generate(text, voice, rate)
            print(f"生成SSML: {ssml_content}")

            # 构建并发送请求
            request_data = self.builder.build_tts_request(ssml_content)
            self.connection.send(request_data)

            # 接收响应
            response = self._receive_full_response()
            return self._parse_response(response)

        finally:
            # 确保连接关闭
            self.connection.close()

    def _receive_full_response(self):
        """接收完整响应"""
        response = b""
        while True:
            chunk = self.connection.receive()
            if not chunk:
                break
            response += chunk
            # 简单判断响应结束（实际应根据Content-Length判断）
            if b"\r\n\r\n" in chunk and len(response) > 1024:
                break
        return response

    def _parse_response(self, response_data):
        """解析服务器响应"""
        # 分离响应头和响应体
        parts = response_data.split(b"\r\n\r\n", 1)
        if len(parts) < 2:
            raise UniMRCPError("无效的响应格式")

        headers, body = parts

        # 解析响应头
        header_lines = headers.decode('utf-8').split('\r\n')
        status_line = header_lines[0]

        # 检查状态码
        if not status_line.startswith("MRCP/2.0 200"):
            raise UniMRCPError(f"服务器返回错误: {status_line}")

        # 提取音频数据
        return body


def main():
    # 配置服务器信息
    MRCP_HOST = "172.17.0.2"  # 替换为实际服务器地址
    MRCP_PORT = 1544  # 替换为实际端口

    # 创建TTS服务实例
    tts_service = UniMRCPTTSService(MRCP_HOST, MRCP_PORT)

    try:
        # 合成语音
        text = "Hello, this is a test of UniMRCP client. 你好，这是UniMRCP客户端测试。"
        audio_data = tts_service.synthesize(
            text=text,
            voice="en-US",
            rate="medium"
        )

        # 保存音频文件
        with open("output.wav", "wb") as f:
            f.write(audio_data)
        print("语音合成成功，已保存到output.wav")

    except UniMRCPError as e:
        print(f"操作失败: {str(e)}")
    except Exception as e:
        print(f"发生错误: {str(e)}")


if __name__ == "__main__":
    main()
